﻿
// ServerDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "Server.h"
#include "ServerDlg.h"
#include "afxdialogex.h"
#include "cJSON.h"
#include "SocketCpp.h"
#include "ServerRDPDlg.h"

// CServerDlg 对话框



CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CServerDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CServerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	//  DDX_Control(pDX, IDC_COMBO_PPI, mPPI);
	//  DDX_Control(pDX, IDC_COMBO_BIT, mBit);
	//  DDX_Control(pDX, IDC_EDIT_PROPORT, mEditPro);
	DDX_Control(pDX, IDC_COMBO_BIT, mComboBit);
	DDX_Control(pDX, IDC_COMBO_PPI, mComboPPI);
	DDX_Control(pDX, IDC_EDIT_DATAPORT, mEditDataPort);
	DDX_Control(pDX, IDC_EDIT_HEIGHT, mEditHeight);
	//  DDX_Control(pDX, IDC_EDIT_PROPORT, m_EditProPort);
	DDX_Control(pDX, IDC_EDIT_WIDTH, mEditWidth);
	DDX_Control(pDX, IDC_EDIT_X, mEditX);
	DDX_Control(pDX, IDC_EDIT_Y, mEditY);
	DDX_Control(pDX, IDC_STATIC_STATUS, mStaticStatus);
	DDX_Control(pDX, IDC_EDIT_PROPORT, mEditProPort);
	//  DDX_Control(pDX, IDC_EDIT_CLIHEIGHT, mEditCliHeight);
	//  DDX_Control(pDX, IDC_EDIT_CLIWIDTH, mEditCliWidth);
	DDX_Control(pDX, IDC_COMBO_FPS, mComboFPS);
}

BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, &CServerDlg::OnClickedButton1)
	ON_CBN_SELCHANGE(IDC_COMBO_PPI, &CServerDlg::OnSelchangeComboPpi)
	ON_MESSAGE(WM_NETMSG, &CServerDlg::OnNetmsg)
	ON_WM_CLOSE()
	ON_MESSAGE(WM_BEGINRDP, &CServerDlg::OnBeginRDP)
END_MESSAGE_MAP()


BOOL CServerDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	ShowWindow(SW_SHOW);

	// 初始化默认参数
	mEditProPort.SetWindowTextW(_T("20000"));
	mEditDataPort.SetWindowTextW(_T("20001"));
	mComboPPI.SetCurSel(0);
	mComboBit.SetCurSel(2);
	mComboFPS.SetCurSel(4);
	mEditHeight.SetWindowTextW(_T("100"));
	mEditWidth.SetWindowTextW(_T("100"));
	mEditX.SetWindowTextW(_T("8"));
	mEditY.SetWindowTextW(_T("6"));
	UpdateUIData();

	mButtonPushed = FALSE;

	WSADATA wsaData;
	int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != NO_ERROR)
		AfxMessageBox(_T("WSAStartup错误"));
	
	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CServerDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
HCURSOR CServerDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void CServerDlg::OnClickedButton1()
{
	if (!mButtonPushed)
	{
		StartProtocolListen();
		GetDlgItem(IDC_BUTTON1)->SetWindowTextW(_T("停止服务"));
		mButtonPushed = TRUE;
	}
	else
	{
		StopProtocolListen();
		GetDlgItem(IDC_BUTTON1)->SetWindowTextW(_T("开启服务"));
		mButtonPushed = FALSE;
	}
}


void CServerDlg::OnSelchangeComboPpi()
{
	// 分辨率选择响应函数
	// 计算参数填入对应控件
	CString strX, strY, strWidth, strHeight;
	switch (mComboPPI.GetCurSel())
	{
	case 0:		//800 x 600
		strX = _T("8");
		strY = _T("6");
		strWidth = _T("100");
		strHeight = _T("100");
		break;
	case 1:		//1024 x 768
		strX = _T("8");
		strY = _T("6");
		strWidth = _T("128");
		strHeight = _T("128");
		break;
	case 2:		//1280 x 800
		strX = _T("10");
		strY = _T("10");
		strWidth = _T("128");
		strHeight = _T("80");
		break;
	case 3:		//1440 x 900
		strX = _T("12");
		strY = _T("12");
		strWidth = _T("120");
		strHeight = _T("75");
		break;
	default:
		break;
	}

	mEditHeight.SetWindowTextW(strHeight);
	mEditWidth.SetWindowTextW(strWidth);
	mEditX.SetWindowTextW(strX);
	mEditY.SetWindowTextW(strY);
	UpdateUIData();
}


/*
 @ 协议通讯的网络消息响应
 @ 包括accept、读写、关闭等
*/
afx_msg LRESULT CServerDlg::OnNetmsg(WPARAM wParam, LPARAM lParam)
{
	SOCKET s = (SOCKET)wParam;
	switch (WSAGETSELECTEVENT(lParam))
	{
	case FD_ACCEPT:
	{
		sockaddr_in    m_client;
		int sz = sizeof(sockaddr_in);
		SOCKET acp = accept(s, (sockaddr*)&m_client, &sz);
		if (acp == INVALID_SOCKET)
		{
			return 0;
		}
		CString strStatus , strMsgBox;
		mIP.Format(_T("%u.%u.%u.%u"), NIPQUAD(m_client.sin_addr.s_addr));
		strStatus.Format(_T("有一个客户端连接：[%u.%u.%u.%u]"), NIPQUAD(m_client.sin_addr.s_addr));
		strMsgBox.Format(_T("收到[%u.%u.%u.%u]连接，是否发送配置并启动远程桌面？"), NIPQUAD(m_client.sin_addr.s_addr));
		mStaticStatus.SetWindowTextW(strStatus);
		if (IDYES == AfxMessageBox(strMsgBox, MB_YESNO | MB_ICONQUESTION))
		{
			//发送开始远程桌面传输消息给窗口（异步）
			PostMessage(WM_BEGINRDP, 0, 0);
			//构造json字符串并发送
			cJSON *json = cJSON_CreateObject();
			cJSON_AddItemToObject(json, "FinalBlockWidth", cJSON_CreateNumber(mServerWidth / mX));
			cJSON_AddItemToObject(json, "FinalBlockHeight", cJSON_CreateNumber(mServerHeight / mY));
			cJSON_AddItemToObject(json, "FinalBit", cJSON_CreateNumber(mBit));
			cJSON_AddItemToObject(json, "TimeCell", cJSON_CreateNumber(mTimeCell));
			cJSON_AddItemToObject(json, "FinalX", cJSON_CreateNumber(mX));
			cJSON_AddItemToObject(json, "FinalY", cJSON_CreateNumber(mY));
			char *jsonBuf = cJSON_PrintUnformatted(json);
			MySocket socket(acp);
			int res = socket.SendString(jsonBuf, strlen(jsonBuf) + 1);
			cJSON_Delete(json);
			if (res > 0)
			{
				strStatus.Format(_T("发送配置：[%d,%d,%d,%d,%d,%d]"), mServerWidth / mX, mServerHeight / mY, mBit, mTimeCell, mX, mY);
			}
		}
		else
		{
			closesocket(acp);
		}
	}
	break;
	case FD_CLOSE:
	{
		CString strStatus;
		strStatus.Format(_T("客户端断开"));
		mStaticStatus.SetWindowTextW(strStatus);
		closesocket(s);
	}
	break;
	}
	return 0;
}


void CServerDlg::UpdateUIData()
{
	CString strProPort, strDataPort;
	mEditProPort.GetWindowTextW(strProPort);
	mEditDataPort.GetWindowTextW(strDataPort);
	mProPort = _ttoi(strProPort);
	mDataPort = _ttoi(strDataPort);
	switch (mComboPPI.GetCurSel())
	{
	case 0:		//800 x 600
		mServerWidth = 800;
		mServerHeight = 600;
		mX = 8;
		mY = 6;
		break;
	case 1:		//1024 x 768
		mServerWidth = 1024;
		mServerHeight = 768;
		mX = 8;
		mY = 6;
		break;
	case 2:		//1280 x 800
		mServerWidth = 1280;
		mServerHeight = 800;
		mX = 10;
		mY = 10;
		break;
	case 3:		//1440 x 900
		mServerWidth = 1440;
		mServerHeight = 900;
		mX = 12;
		mY = 12;
		break;
	default:
		mServerWidth = 0;
		mServerHeight = 0;
		mX = 0;
		mY = 0;
		break;
	}

	switch (mComboBit.GetCurSel())
	{
	case 0:
		mBit = 8;
		break;
	case 1:
		mBit = 16;
		break;
	case 2:
		mBit = 24;
		break;
	case 3:
		mBit = 32;
		break;
	default:
		mBit = 0;
		break;
	}

	switch (mComboFPS.GetCurSel())
	{
	case 0:
		mTimeCell = 50;
		break;
	case 1:
		mTimeCell = 100;
		break;
	case 2:
		mTimeCell = 200;
		break;
	case 3:
		mTimeCell = 500;
		break;
	case 4:
		mTimeCell = 1000;
		break;
	default:
		mTimeCell = 0;
		break;
	}
}

void CServerDlg::OnClose()
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值
	WSACleanup();
	CDialogEx::OnClose();
}


afx_msg LRESULT CServerDlg::OnBeginRDP(WPARAM wParam, LPARAM lParam)
{
	//创建RDP窗口并配置参数
	CServerRDPDlg *pDlg = new CServerRDPDlg;
	CString strTitle;
	strTitle.Format(_T("\\\\%s [%d x %d %dbit]"), mIP, mServerWidth, mServerHeight, mBit);
	pDlg->SetConfig(mServerWidth, mServerHeight, mX, mY, mDataPort, mBit, strTitle);
	pDlg->Create(CServerRDPDlg::IDD, this);
	pDlg->ShowWindow(SW_SHOW);

	//更新状态栏
	mStaticStatus.SetWindowTextW(_T("启动远程桌面传输窗口..."));
	return 0;
}

void CServerDlg::StartProtocolListen()
{
	UpdateUIData();
	if (mServerWidth <= 0 ||mX <= 0 || mY <=0 || mServerHeight <= 0 || mBit <= 0 || mTimeCell <= 0 || mProPort <= 0 || mDataPort <= 0)
	{
		AfxMessageBox(_T("请正确配置服务器参数"));
		return;
	}

	//启动协商协议网络监听
	ProSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (ProSocket == INVALID_SOCKET)
	{
		AfxMessageBox(_T("创建socket错误"));
		return;
	}
	sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(mProPort);
	sin.sin_addr.S_un.S_addr = INADDR_ANY;
	if (bind(ProSocket, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
	{
		AfxMessageBox(_T("绑定协议端口错误"));
		closesocket(ProSocket);
		return;
	}

	//使用WSAAsyncSelect模型，有客户端连接，给窗口发送WM_NETMSG消息
	if (SOCKET_ERROR == WSAAsyncSelect(ProSocket, this->GetSafeHwnd(), WM_NETMSG, FD_ACCEPT | FD_CLOSE))
	{
		AfxMessageBox(_T("WSAAsyncSelect模型创建错误"));
		closesocket(ProSocket);
		return;
	}

	if (listen(ProSocket, 2) == SOCKET_ERROR)
	{
		AfxMessageBox(_T("监听协议端口错误"));
		closesocket(ProSocket);
		return;
	}
	mStaticStatus.SetWindowTextW(_T("正在监听协议通讯端口..."));
}

void CServerDlg::StopProtocolListen()
{
	closesocket(ProSocket);
	ProSocket = NULL;
	mStaticStatus.SetWindowTextW(_T("就绪!"));
}
